﻿/*
    This file is part of nDoctor Light

    NDoctor is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    NDoctor is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with NDoctor.  If not, see <http://www.gnu.org/licenses/>.
*/
namespace Probel.Ldoc.ViewModels.Pages
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.IO;
    using System.Threading.Tasks;
    using System.Windows.Input;

    using Probel.Ldoc.Services.Dto;
    using Probel.Ldoc.Services.Services;
    using Probel.Ldoc.ViewModels.Dto;
    using Probel.Ldoc.ViewModels.Helpers;
    using Probel.Ldoc.ViewModels.Properties;
    using Probel.Ldoc.ViewModels.ToolBoxes;
    using Probel.Mvvm.DataBinding;
    using Probel.Mvvm.Gui;

    public class RecordEditorViewModel : BaseViewModel
    {
        #region Fields

        private readonly ICommand activateEditionCommand;
        private readonly ICommand addNewRecordCommand;
        private readonly ICommand cancelEditionCommand;
        private readonly RecordEditorViewModelBuilder ChildViewModels;
        private readonly PatientCardDto CurrentPatient;
        private readonly ICommand removeRecordCommand;
        private readonly ICommand renameCommand;
        private readonly IPatientService Service;

        private RecordCardViewModel currentRecord;
        private RecordCabinetViewModel recordCabinet;
        private UiMessageDto uiMessage;

        #endregion Fields

        #region Constructors

        public RecordEditorViewModel(IErrorService errorService
            , IPatientService service
            , PatientCardDto patient
            , bool isAsync = true)
            : base(errorService, isAsync)
        {
            this.ChildViewModels = new RecordEditorViewModelBuilder(this, errorService, service, isAsync);
            this.CurrentPatient = patient;
            this.Service = service;
            this.UiMessage = UiMessageDto.Info(Messages.Msg_Ready);

            this.addNewRecordCommand = new RelayArgCommand(this.AddNewRecord);
            this.removeRecordCommand = new RelayCommand(this.RemoveRecord, this.CanRemoveRecord);
            this.activateEditionCommand = new RelayArgCommand(this.ActivateEdition);
            this.renameCommand = new RelayArgCommand(this.Rename);
            this.cancelEditionCommand = new RelayArgCommand(this.CancelEdition);
        }

        #endregion Constructors

        #region Properties

        public ICommand ActivateEditionCommand
        {
            get { return this.activateEditionCommand; }
        }

        public ICommand AddNewRecordCommand
        {
            get { return this.addNewRecordCommand; }
        }

        public ICommand CancelEditionCommand
        {
            get { return this.cancelEditionCommand; }
        }

        public string CurrentPatientName
        {
            get
            {
                return string.Format("{0} {1}", this.CurrentPatient.FirstName, this.CurrentPatient.LastName);
            }
        }

        public RecordCardViewModel CurrentRecord
        {
            get { return this.currentRecord; }
            set
            {
                this.currentRecord = value;
                this.OnPropertyChanged(() => CurrentRecord);
            }
        }

        public RecordCabinetViewModel RecordCabinet
        {
            get { return this.recordCabinet; }
            set
            {
                this.recordCabinet = value;
                this.OnPropertyChanged(() => RecordCabinet);
            }
        }

        public ICommand RemoveRecordCommand
        {
            get { return this.removeRecordCommand; }
        }

        public ICommand RenameCommand
        {
            get { return this.renameCommand; }
        }

        public UiMessageDto UiMessage
        {
            get { return this.uiMessage; }
            set
            {
                this.uiMessage = value;
                this.OnPropertyChanged(() => UiMessage);
            }
        }

        #endregion Properties

        #region Methods

        public CreateFileViewModel BuildFileViewModel()
        {
            return this.ChildViewModels.BuildFileViewModel();
        }

        public CreateFolderViewModel BuildFolderViewModel()
        {
            return this.ChildViewModels.BuildFolderViewModel();
        }

        public MacroEditorViewModel BuildMacroEditorViewModel()
        {
            return this.ChildViewModels.BuildMacroEditorViewModel(this.CurrentPatient);
        }

        public RecordHistoryViewModel BuildRecordHistoryViewModel()
        {
            return this.ChildViewModels.BuildRecordHistoryViewModel(this.CurrentRecord);
        }

        public RenameRecordViewModel BuildRenameRecordViewModel()
        {
            return this.ChildViewModels.BuildRenameRecordViewModel(this.CurrentRecord);
        }

        public void CreateRecord(RecordCardDto record, RecordDrawerCardDto folder)
        {
            this.Async(() => this.Service.Create(record, folder, this.CurrentPatient)
                     , () =>
                     {
                         this.Refresh();
                         this.UiMessage = UiMessageDto.Info(Messages.Msg_CreatedRecord);
                     });
        }

        public IEnumerable<MacroDto> GetMacros()
        {
            return this.Service.GetMacros(this.CurrentPatient);
        }

        public string GetRecordRtf()
        {
            var rtf = this.Service.GetRtfFromRecord(this.CurrentRecord.ToDto());
            this.UiMessage = UiMessageDto.Info(Messages.Msg_RecordLoaded);
            return rtf;
        }

        public void Refresh()
        {
            this.Async(() => this.Service.GetRecordsCabinet(this.CurrentPatient),
                r => this.RecordCabinet = new RecordCabinetViewModel(r, this.ErrorService, this.Service, IsAsync));
        }

        public void SaveRecordAsync(string rtf, Action guiProcess)
        {
            this.Async(() =>
            {
                this.Service.SaveRtf(this.CurrentRecord.ToDto(), rtf);
                this.CurrentRecord.RefreshDates();

            }, () =>
            {
                this.UiMessage = UiMessageDto.Info(Messages.Msg_RecordSaved);
                guiProcess();
            }); ;
        }

        public RecordCardViewModel ToViewModel(RecordCardDto recordCard)
        {
            return new RecordCardViewModel(recordCard, this.ErrorService, this.Service, this.IsAsync);
        }

        internal IEnumerable<RecordDrawerCardDto> GetRecordFolders()
        {
            return this.Service.GetRecordsDrawers();
        }

        private void ActivateEdition(object arg)
        {
            if (arg is TreeViewModel)
            {
                var vm = arg as TreeViewModel;
                if (!vm.IsEditing) { vm.IsEditing = true; }
            }
        }

        private void AddNewRecord(object arg)
        {
            if (arg is long)
            {
                var ok = ViewService.MessageBox.Question(Messages.Msg_ConfirmNewRecord);
                if (ok)
                {
                    var id = (long)arg;
                    this.Async(() => this.Service.CreateDefaultRecord(new RecordDrawerDto() { Id = id }, this.CurrentPatient)
                             , () =>
                             {
                                 this.Refresh();
                                 this.UiMessage = UiMessageDto.Info(Messages.Msg_RecordAdded);
                             });
                }
            }
        }

        private void CancelEdition(object arg)
        {
            if (arg is TreeViewModel)
            {
                var vm = arg as TreeViewModel;
                if (vm.IsEditing) { vm.IsEditing = false; }
            }
        }

        private bool CanRemoveRecord()
        {
            return this.CurrentRecord != null
                && ViewService.MessageBox.Question(Messages.Msg_ConfirmNewRecord);
        }

        private void RemoveRecord()
        {
            this.Async(() => this.Service.Remove(this.CurrentRecord.ToDto())
                , () =>
                {
                    this.Refresh();
                    this.CurrentRecord = null;
                    this.UiMessage = UiMessageDto.Info(Messages.Msg_RecordRemoved);
                });
        }

        private void Rename(object arg)
        {
            if (arg is TreeViewModel)
            {
                var vm = arg as TreeViewModel;
                if (vm.RenameCommand.CanExecute(null))
                {
                    vm.RenameCommand.Execute(null);
                    vm.IsEditing = false;
                    this.UiMessage = UiMessageDto.Info(Messages.Msg_ItemRenamed);
                    this.Refresh();
                }
                else
                {
                    ViewService.MessageBox.Warning(Messages.Msg_RenameWithEmptyString);
                    vm.IsEditing = false;
                }
            }
        }

        #endregion Methods
    }
}